using System;
using Godot;

namespace Arcane.Source.Client.Extensions;

public static class VariantExt
{
    #region Operations
    private static Expression add = null;
    public static Variant Add(this Variant lhs, Variant rhs)
    {
        if (add == null)
        {
            add = new Expression();
            add.Parse("l+r", ["l", "r"]);
        }
        return add.Execute([lhs, rhs]);
    }

    private static Expression sub = null;
    public static Variant Sub(this Variant lhs, Variant rhs)
    {
        if (sub == null)
        {
            sub = new Expression();
            sub.Parse("l-r", ["l", "r"]);
        }
        return sub.Execute([lhs, rhs]);
    }

    private static Expression mul = null;
    public static Variant Mul(this Variant lhs, Variant rhs)
    {
        if (mul == null)
        {
            mul = new Expression();
            mul.Parse("l*r", ["l", "r"]);
        }
        return mul.Execute([lhs, rhs]);
    }

    private static Expression div = null;
    public static Variant Div(this Variant lhs, Variant rhs)
    {
        if (div == null)
        {
            div = new Expression();
            div.Parse("l/r", ["l", "r"]);
        }
        return div.Execute([lhs, rhs]);
    }

    private static Expression eq = null;
    public static Variant Eq(this Variant lhs, Variant rhs)
    {
        if (eq == null)
        {
            eq = new Expression();
            eq.Parse("l==r", ["l", "r"]);
        }
        return eq.Execute([lhs, rhs]);
    }

    private static Expression lt = null;
    public static Variant Lt(this Variant lhs, Variant rhs)
    {
        if (lt == null)
        {
            lt = new Expression();
            lt.Parse("l<r", ["l", "r"]);
        }
        return lt.Execute([lhs, rhs]);
    }

    private static Expression gt = null;
    public static Variant Gt(this Variant lhs, Variant rhs)
    {
        if (gt == null)
        {
            gt = new Expression();
            gt.Parse("l>r", ["l", "r"]);
        }
        return gt.Execute([lhs, rhs]);
    }

    private static Expression le = null;
    public static Variant Le(this Variant lhs, Variant rhs)
    {
        if (le == null)
        {
            le = new Expression();
            le.Parse("l<=r", ["l", "r"]);
        }
        return le.Execute([lhs, rhs]);
    }

    private static Expression ge = null;
    public static Variant Ge(this Variant lhs, Variant rhs)
    {
        if (ge == null)
        {
            ge = new Expression();
            ge.Parse("l>=r", ["l", "r"]);
        }
        return ge.Execute([lhs, rhs]);
    }

    private static Expression ne = null;
    public static Variant Ne(this Variant lhs, Variant rhs)
    {
        if (ne == null)
        {
            ne = new Expression();
            ne.Parse("l!=r", ["l", "r"]);
        }
        return ne.Execute([lhs, rhs]);
    }
    #endregion

    public static object AsObj(this Variant variant, Type type)
    {
        if (type == typeof(bool)) return variant.AsBool();
        if (type == typeof(byte)) return variant.AsByte();
        if (type == typeof(short)) return variant.AsInt16();
        if (type == typeof(ushort)) return variant.AsUInt16();
        if (type == typeof(int)) return variant.AsInt32();
        if (type == typeof(uint)) return variant.AsUInt32();
        if (type == typeof(long)) return variant.AsInt64();
        if (type == typeof(ulong)) return variant.AsUInt64();
        if (type == typeof(float)) return variant.AsSingle();
        if (type == typeof(double)) return variant.AsDouble();
        if (type == typeof(string)) return variant.AsString();
        if (type == typeof(StringName)) return variant.AsStringName();
        if (type.IsSubclassOf(typeof(GodotObject))) return variant.AsGodotObject();

        #if DEBUG
        GD.PrintErr($"Unsupported type: {type.FullName}");
        #endif
        return null;
    }
}